#pragma once

#include <Windows.h>
#include <Commctrl.h>
#include "win/win_base.h"
#include "win/win_frame.h"
#include "win/text_container.h"
#include <string>
#include <vector>

#define MAX_PROMPT              16
#define TIMER_CARET             0x1001


class cmd_history
{
public:
    cmd_history() : _cursor(0)          {}
    ~cmd_history()                      {}

    void    reset_cursor()              { _cursor = (int)_history.size(); }
    void    add(const wchar_t* pwscmd);
    STRING::unicode search_forward(const wchar_t* keyword);
    STRING::unicode search_backward(const wchar_t* keyword);

private:
    int                                 _cursor;
    std::vector<STRING::unicode>        _history;
};


class win_cmd : public text_container, public win_tile
{
public:
    win_cmd();
    ~win_cmd();

///////////////////////////////////////////////////////////////////////////////
// inherit from class win_base
public:
    virtual bool    create(HWND hWndParent);
    virtual LRESULT OnLeftDown(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown);
	virtual LRESULT OnLeftUp(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown);
	virtual LRESULT OnLeftDoubleClick(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown);
    virtual LRESULT OnRightDown(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown);
	virtual LRESULT OnMouseMove(DWORD dwKeys, WORD x, WORD y);
	virtual LRESULT OnMouseWheel(WORD x, WORD y, WORD key, short distance);
    virtual LRESULT OnSize(DWORD dwFlags, WORD width, WORD height);
	virtual LRESULT OnHorScroll(int scrollCode, int pos, HWND scrollBar);
    virtual LRESULT OnVerScroll(int scrollCode, int pos, HWND scrollBar);
    virtual LRESULT OnEraseBackground(HDC hDC) {return 0;}
    virtual LRESULT OnPaint();
    virtual LRESULT OnChar(DWORD dwKey, DWORD dwData);
	virtual LRESULT OnKeyDown(DWORD dwKey, DWORD dwKeyData);
    virtual LRESULT OnTimer(DWORD dwTimerID, TIMERPROC* pTimeProc);
// 
///////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////
// reserved event interfaces for instance inherit
public:
    virtual void    OnInit()                            {}
    virtual void    OnRelease()                         {}
    virtual void    OnCommand(const wchar_t* pwcmd)     {}
    virtual void    OnSwitch()                          {}
//
///////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////
// input management functions
public:
    void            clear_view();   // clear output content
    void            update_view();  // called when window size changed or content changed
    void            output(const wchar_t* pwszText);
    void            scroll_view_bottom();
    bool            scroll_at_bottom()          { return get_v_scroll() == get_max_v_scroll(); }
    void            set_view_lines(int count)    { _max_lines = count; }
//
///////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////
// input management functions
public:
    inline void         set_input_prompt(const wchar_t* prompt) { _prompt = STRING::unicode(prompt); input_clear(); }
    inline void         input_clear()       { remove_text(line_range(line_count() - 1)); insert_text(TEXT_END, *_prompt); }
    inline int          input_head()        { return _line_buffer.back().range.begin + _prompt.length(); }
    inline int          input_tail()        { return _line_buffer.back().range.end; }
    inline int          input_length()      { return input_tail() - input_head(); }
    inline int          input_pos()         { return _caret_pos - input_head(); }
    STRING::unicode     input_text()        { text_range r={input_head(), input_tail()}; return get_text(r); }
    void                move_input(int pos, bool marked = false);

    void                paste_text(const wchar_t* pwtext);

    void                copy_to_clipboard(wchar_t* pwtext);
    STRING::unicode     get_clipboard_text();
//
///////////////////////////////////////////////////////////////////////////////


// content functions
public:

    STRING::unicode _prompt;
    int             _max_lines;
    int             _select_from;
    POINT           _drag_pt;
    int             _caret_flag;
    int             _cmd_type;
    cmd_history     _cmd_history;
};
